#pragma once
#include <brpc/server.h>
#include <utility>
#include "base.pb.h"
#include "user.pb.h"
#include "transmite.pb.h"

#include "chat_session_member-odb.hxx"

#include "etcd.hpp"
#include "channel.hpp"
#include "mysql_chat_session_member.hpp"
#include "utils.hpp"
#include "rabbitmq.hpp"

class MsgTransmitServiceImpl : public chat_system::MsgTransmitService {
public:
    using ptr = std::shared_ptr<MsgTransmitServiceImpl>;


    MsgTransmitServiceImpl(
        std::shared_ptr<odb::core::database> mysql_client,
        ServiceManager::ptr user_service_channel,
        const std::string& user_service_name, 
        const std::string& exchange_name,
        const std::string& routing_key,
        RabbitMQClient::ptr rabbitmq_client)
    : _chat_session_member_table(std::make_shared<ChatSessionMemberTable>(mysql_client))
    , _user_service_channel(user_service_channel)
    , _user_service_name(user_service_name)
    , _exchange_name(exchange_name)
    , _routing_key(routing_key)
    , _rabbitmq_client(rabbitmq_client) {}




    virtual void GetTransmitTarget(::google::protobuf::RpcController* controller,
                       const ::chat_system::NewMessageReq* request,
                       ::chat_system::GetTransmitTargetRsp* response,
                       ::google::protobuf::Closure* done) override {
        auto err_handle = [&response, &request](const std::string& err_msg)->void {
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg(err_msg);
        };
        brpc::ClosureGuard guard(done);
        LOG_INFO("收到消息转发请求: {}", request->ShortDebugString());


        std::string chat_session_id = request->chat_session_id();
        std::string user_id = request->user_id();


        //获取用户服务信道管理对象
        auto channel_manager = _user_service_channel->choose(_user_service_name);
        if(channel_manager == nullptr) {
            err_handle("获取用户服务信道失败");
            LOG_DEBUG("GetTransmitTarget 失败: 获取用户服务信道失败");
            return;
        }
        // 获取用户服务信道
        auto channel = channel_manager->choose();
        if(channel == nullptr) {
            err_handle("获取用户服务信道失败");
            LOG_DEBUG("GetTransmitTarget 失败: 获取用户服务信道失败");
            return;
        }


        // 获取用户信息
        chat_system::GetUserInfoReq req;
        req.set_request_id(request->request_id());
        req.set_user_id(user_id);
        chat_system::UserService_Stub stub(channel.get());
        chat_system::GetUserInfoRsp user_rsp;
        brpc::Controller cntl;
        stub.GetUserInfo(&cntl, &req, &user_rsp, nullptr);
        if(cntl.Failed() || !user_rsp.success()) {
            err_handle("获取用户信息失败");
            LOG_DEBUG("GetTransmitTarget 失败: 获取用户信息失败, {}", cntl.ErrorText());
            return;
        }

        
        // 组织消息结构
        chat_system::MessageInfo rsp_info;
        rsp_info.set_message_id(uuid());
        rsp_info.set_chat_session_id(chat_session_id);
        rsp_info.set_timestamp(time(nullptr));
        rsp_info.mutable_sender()->CopyFrom(user_rsp.user_info());
        rsp_info.mutable_message()->CopyFrom(request->message());



        // 将消息发布到RabbitMQ
        LOG_DEBUG("序列化后消息 : {}", rsp_info.SerializeAsString());
        bool success = _rabbitmq_client->publish(_exchange_name, rsp_info.SerializeAsString(), _routing_key);
        if(!success) {
            err_handle("发布消息到RabbitMQ失败");
            LOG_DEBUG("GetTransmitTarget 失败: 发布消息到RabbitMQ失败");
            return;
        }



        // 获取会话成员列表
        std::vector<std::string> member_list = _chat_session_member_table->members(chat_session_id);
        if (member_list.empty()) {
            err_handle("获取聊天会话成员列表失败");
            LOG_DEBUG("GetTransmitTarget 失败: 获取聊天会话成员列表失败");
            return;
        }


        // 组织响应
        response->set_request_id(request->request_id());
        response->set_success(true);
        response->mutable_message()->CopyFrom(rsp_info);
        for (auto& member : member_list) {
            if(member == user_id) {
                continue; // 不需要给自己转发
            }
            response->mutable_target_id_list()->Add(std::move(member));
        }
    }
    


private:
    ChatSessionMemberTable::ptr _chat_session_member_table;
    ServiceManager::ptr _user_service_channel;
    std::string _user_service_name;
    // RabbitMQ客户端
    std::string _exchange_name;
    std::string _routing_key;
    RabbitMQClient::ptr _rabbitmq_client;
};


class TransmiteServer {
public:
    using ptr = std::shared_ptr<TransmiteServer>;

    TransmiteServer (Registry::ptr registry_client,
                Discovery::ptr discovery_client,
                std::shared_ptr<odb::core::database> mysql_client,
                RabbitMQClient::ptr rabbitmq_client,
                std::shared_ptr<brpc::Server> server)
    : _registry_client(registry_client)
    , _discovery_client(discovery_client)
    , _mysql_client(mysql_client)
    , _rabbitmq_client(rabbitmq_client)
    , _server(server) {}


    void start() {
        LOG_INFO("消息转发服务已启动");
        _server->RunUntilAskedToQuit();
    }

private:
    Registry::ptr _registry_client;
    Discovery::ptr _discovery_client;

    std::shared_ptr<odb::core::database> _mysql_client;
    RabbitMQClient::ptr _rabbitmq_client;
    std::shared_ptr<brpc::Server> _server;
};


class TransmiteServerBuilder { 
public:
    void make_rabbitmq_object(const std::string &user,
                   const std::string &password,
                   const std::string &host, 
                   const std::string &exchange_name,
                   const std::string &queue_name, 
                   const std::string &bind_key) {
        _rabbitmq_client = std::make_shared<RabbitMQClient>(user, password, host);
        _exchange_name = exchange_name;
        _routing_key = bind_key;
        LOG_DEBUG("声明RabbitMQ交换机: {}, 队列: {}, 路由键: {}", _exchange_name, queue_name, _routing_key);
        _rabbitmq_client->declareComponents(_exchange_name, queue_name, _routing_key);
    }


    void make_reg_object(const std::string &etcd_host, const std::string& service_name, const std::string service_host) {
        _registry_client = std::make_shared<Registry>(etcd_host);
        bool success = _registry_client->registry(service_name, service_host);
        if(!success)
        {
            LOG_ERROR("注册服务到etcd失败");
            return;
        }
        LOG_INFO("注册服务{} - {}到etcd成功", service_name, service_host);
    }


    void make_rpc_object(uint16_t port, int32_t timeout, uint8_t num_threads) {
        logging::LoggingSettings tmp_log;
        tmp_log.logging_dest = logging::LOG_TO_NONE;
        logging::InitLogging(tmp_log);
        _server = std::make_shared<brpc::Server>();
        int ret = _server->AddService(_transmite_service_impl.get(), brpc::SERVER_DOESNT_OWN_SERVICE);
        if(ret < 0)
        {
            LOG_ERROR("注册服务失败");
            return;
        }
        brpc::ServerOptions options;
        options.idle_timeout_sec = timeout;
        options.num_threads = num_threads;
        ret = _server->Start(port, &options);
        if(ret < 0)
        {
            LOG_ERROR("启动服务器失败");
            abort();  
        }
    }

    // 
    void make_discovery_object(const std::string &etcd_host, const std::string &basedir, const std::string &service_name) {
        _user_service_name = basedir + service_name;
        _service_manager = std::make_shared<ServiceManager>();     
        _service_manager->declared(_user_service_name);   
        auto put_cb = std::bind(&ServiceManager::onServiceOnline, _service_manager, std::placeholders::_1, std::placeholders::_2);
        auto del_cb = std::bind(&ServiceManager::onServiceOffline, _service_manager, std::placeholders::_1, std::placeholders::_2);
        _discovery_client = std::make_shared<Discovery>(etcd_host, _user_service_name, put_cb, del_cb);
        if(_discovery_client == nullptr)
        {
            LOG_ERROR("创建服务发现对象失败");
            abort();
        }
        
    }


    void make_mysql_object(
        const std::string &user,
        const std::string &pswd,
        const std::string &host,
        const std::string &db,
        const std::string &cset,
        int port,
        int conn_pool_count) {
        _mysql_client = ODBFactory::create(user, pswd, db, host, port, cset, conn_pool_count);
    }



    void make_transmite_service_impl() {
        _transmite_service_impl = std::make_shared<MsgTransmitServiceImpl>(_mysql_client, 
        _service_manager, _user_service_name, _exchange_name, _routing_key, _rabbitmq_client);
    }
    TransmiteServer::ptr build() {
        if(_transmite_service_impl == nullptr)
        {
            LOG_ERROR("用户服务实例未创建");
            return nullptr;
        }
        if(_registry_client == nullptr)
        {
            LOG_ERROR("注册中心对象未创建");
            return nullptr;
        }
        if(_server == nullptr)
        {
            LOG_ERROR("RPC服务器对象未创建");
            return nullptr;
        }


        if(_discovery_client == nullptr)
        {
            LOG_ERROR("服务发现对象未创建");
            return nullptr;
        }

        return std::make_shared<TransmiteServer>(_registry_client, _discovery_client, _mysql_client, _rabbitmq_client, _server);
    }
private:
    std::string _user_service_name;
    MsgTransmitServiceImpl::ptr _transmite_service_impl;
    
    Registry::ptr _registry_client;
    Discovery::ptr _discovery_client;
    ServiceManager::ptr _service_manager;

    std::shared_ptr<odb::core::database> _mysql_client;

    std::string _exchange_name;
    std::string _routing_key;
    RabbitMQClient::ptr _rabbitmq_client;

    std::shared_ptr<brpc::Server> _server;
};    
